package cqie.frame.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cqie.frame.entity.*;
import cqie.frame.entity.po.MenuRoleUserPo;
import cqie.frame.entity.po.SysMenuPo;
import cqie.frame.entity.po.UserRoleMenuPo;
import cqie.frame.entity.qo.SysMenuQo;
import cqie.frame.entity.qo.SysRoleQo;
import cqie.frame.entity.vo.SysMenuTreeData;
import cqie.frame.entity.vo.SysMenuVo;
import cqie.frame.entity.vo.SysRoleVo;
import cqie.frame.entity.vo.SysUserVo;
import cqie.frame.response.CodeMsg;
import cqie.frame.response.ResultJson;
import cqie.frame.service.*;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.User;
import org.apache.logging.log4j.util.PerformanceSensitive;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import org.thymeleaf.util.StringUtils;

import javax.management.relation.Role;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 此表为菜单表，表明菜单的基本信息，如ID，名称，路径，图标等。 前端控制器
 * </p>
 *
 * @author HHL
 * @since 2021-09-02
 */
@RestController
@RequestMapping("/menu")
public class SysMenuController {

    @Autowired
    ISysUserService iSysUserService;
    @Autowired
    ISysMenuService iSysMenuService;
    @Autowired
    ISysRoleService iSysRoleService;
    @Autowired
    IRoleMenuService iRoleMenuService;
    @Autowired
    IUserRoleService iUserRoleService;


    //新增菜单
    @ApiOperation(value = "新增菜单", notes = "新增菜单，同时更新菜单表。", response = SysMenu.class)
    @PostMapping(value = "/addMenu")
    public ResultJson addMenu(SysMenuPo po) {
        try {
            //构造mo
            SysMenu sysMenu = new SysMenu();
            //复制po的属性到sysMenu,第三个参数可选，为忽略某些属性
            BeanUtils.copyProperties(po, sysMenu);
            //插入菜单表后回显插入菜单的主键id
            iSysMenuService.save(sysMenu);
            po.setId(sysMenu.getId());
            //返回菜单
            return ResultJson.success(po);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //批量删除菜单
    @ApiOperation(value = "删除选中菜单", notes = "删除菜单，同时更新角色菜单表。")
    @PostMapping(value = "/deleteCheckMenu")
    public ResultJson deleteCheckMenu(@RequestBody Long[] menuIdList) {
        try {
            for (int i = 0; i < menuIdList.length; i++) {
                //选择器，只有RoleMenu的menuid等同于要删除菜单的id，才执行删除角色菜单表
                QueryWrapper<RoleMenu> qw = new QueryWrapper<>();
                qw.eq("menuId", menuIdList[i]);
                iRoleMenuService.remove(qw);
            }
            for (int i = 0; i < menuIdList.length; i++) {
                //删除菜单表
                iSysMenuService.removeById(menuIdList[i]);
            }
            return ResultJson.success("删除成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //删除菜单
    @ApiOperation(value = "删除单个菜单", notes = "删除菜单，同时更新角色菜单表。")
    @GetMapping(value = "/deleteMenu")
    public ResultJson deleteMenu(long id) {
        try {

            //先删除菜单和角色的关系
            QueryWrapper<RoleMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("menuId", id);
            iRoleMenuService.remove(queryWrapper);
            //最后删除  菜单
            iSysMenuService.removeById(id);
            return ResultJson.success("删除成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //修改菜单
    @ApiOperation(value = "修改菜单", notes = "修改菜单，同时更新角色菜单表。")
    @PostMapping(value = "/updateMenu")
    public ResultJson updateMenu(@RequestBody SysMenuPo po) {
        try {
            SysMenu sysMenu = new SysMenu();
            //复制po的属性到sysMenu,第三个参数可选，为忽略某些属性
            BeanUtils.copyProperties(po, sysMenu);
            if (sysMenu.getId() == null) {
                iSysMenuService.save(sysMenu);
                return ResultJson.success("新增成功");
            }
            if (po.getParentId() == null) {
                sysMenu.setParentId(null);
            }
            iSysMenuService.updateById(sysMenu);
            return ResultJson.success("修改成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

//    //菜单条件分页查询
//    @PostMapping(value = "/menuListPages")
//    @ApiOperation(value = "菜单分页查询", response = SysMenu.class)
//    public ResultJson menuListPages(@RequestBody SysMenuQo qo) {
//        try {
//            //分页参数的配置
//            Page<SysMenu> page = new Page<>(qo.getPageIndex(), qo.getPageSize());
//            //查询条件,是否输入查询条件，如菜单名称，父级Id等
//            //是否查询用户名
//            QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
//            if (!StringUtils.isEmpty(qo.getName())) {
//                //不为空，启用查询
//                //查询模糊查询
//                queryWrapper.like("name", qo.getName());
//            }
//            //是否查询状态
//            if (qo.getParentId() != null) {
//                //不为空，启用查询
//                queryWrapper.eq("parentId", qo.getParentId());
//            }
//            //根据条件以及分页查询
//            IPage<SysMenu> resultPage = iSysMenuService.page(page, queryWrapper);
//
//            return ResultJson.success(resultPage);
//        } catch (Exception e) {
//            return ResultJson.error(CodeMsg.SERVER_ERROR);
//        }
//    }

    //根据菜单ID进入菜单的详细页面
    @ApiOperation(value = "菜单详情")
    @GetMapping(value = "selectMenuById")
    public ResultJson selectMenuById(long id) {
        try {
            //菜单po类
            SysMenuPo po = new SysMenuPo();
            //1.菜单信息
            //先根据菜单id查到菜单
            SysMenu sysMenu = iSysMenuService.getById(id);
            //复制sysMenu的属性到po,第三个参数可选，为忽略某些属性
            BeanUtils.copyProperties(sysMenu, po);
            if (sysMenu.getParentId() != null) {
                QueryWrapper<SysMenu> queryWrapper = new QueryWrapper();
                queryWrapper.eq("id", sysMenu.getParentId());
                SysMenu sysMenu1 = iSysMenuService.getOne(queryWrapper);
                po.setParentName(sysMenu1.getName());
            }
//            //2.菜单对应角色信息，根据菜单id查询角色菜单中间表
//            QueryWrapper<RoleMenu> queryWrapper = new QueryWrapper();
//            queryWrapper.eq("menuId", id);
//            List<RoleMenu> roleMenuList = iRoleMenuService.list(queryWrapper);
//            //角色信息
//            List<SysRole> roleList = new ArrayList<>();
//            //根据角色菜单表查询出角色表
//            roleMenuList.forEach(x -> {
//                SysRole sysRole = new SysRole();
//                //根据角色菜单表的角色id查询出角色信息
//                sysRole = iSysRoleService.getById(x.getRoleId());
//                roleList.add(sysRole);
//            });
//            //把角色List插入到菜单po类
//            po.setRoleList(roleList);
//            //3.角色对应用户信息，根据角色id查询用户角色中间表
//            List<UserRole> userRoleList = new ArrayList<>();
//            roleList.forEach(x->{
//                //一个或多个角色对应的用户角色表
//                List<UserRole> userRoleList1 = new ArrayList<>();
//                QueryWrapper<UserRole> queryWrapper1 = new QueryWrapper<>();
//                queryWrapper1.eq("roleId",x.getId());
//                userRoleList1 = iUserRoleService.list(queryWrapper1);
//                userRoleList.addAll(userRoleList1);
//            });
//            //用户信息
//            List<SysUser> userList = new ArrayList<>();
//            //根据用户角色表查询出用户
//            userRoleList.forEach(x -> {
//                SysUser sysUser = new SysUser();
//                sysUser = iSysUserService.getById(x.getUserId());
//                //初次插入用户
//                if (userList.size()==0) {
//                    //根据用户角色的用户id查询出用户信息
//                    userList.add(sysUser);
//                }else {
//                    //判断是否有角色中重复的用户
//                    for (int i = 0; i < userList.size(); i++) {
//                        //说明重复，停止循环
//                        if (sysUser.getId() == userList.get(i).getId()) {
//                            break;
//                        }
//                        //找完list都无重复用户，插入list
//                        if (i == userList.size() - 1) {
//                            userList.add(sysUser);
//                        }
//                    }
//                }
//            });
//            //把用户List插入到菜单po类
//            po.setUserList(userList);
            return ResultJson.success(po);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }


//    //树表
//    @ApiOperation(value = "树表", notes = "", response = SysMenuVo.class)
//    @GetMapping(value = "/ListTreeData")
//    public ResultJson ListTreeData() {
//        List<SysMenu> treeData = new ArrayList<>();
//
//        List<SysMenu> all = iSysMenuService.list(null);
//        List<SysMenu> first = all.stream()
//                .filter(x -> x.getParentId() == null)
//                .sorted(Comparator.comparing(SysMenu::getSortCode))
//                .collect(Collectors.toList());
//        for (SysMenu mo : first) {
//            addSelfAndChildren(mo, treeData, all);
//        }
//        return ResultJson.success(treeData);
//    }
//
//    /**
//     * 递归方法--添加自己及自己的子女到树形结构
//     */
//    private void addSelfAndChildren(SysMenu mo, List<SysMenu> treeData, List<SysMenu> all) {
//        //添加自己
//        treeData.add(mo);
//        //查找子女
//        List<SysMenu> children = all.stream().filter(x -> x.getParentId() != null && x.getParentId().equals(mo.getId())).sorted(Comparator.comparing(SysMenu::getSortCode)).collect(Collectors.toList());
//        //递归添加子女
//        for (SysMenu child : children) {
//            addSelfAndChildren(child, treeData, all);
//        }
//    }
//

    //树表第二版本
    @ApiOperation(value = "树表2", notes = "构造Element——UI需要的树形结构")
    @GetMapping(value = "/ListTreeData2")
    public ResultJson ListTreeData2() {
        try {
            List<SysMenuTreeData> ret = new ArrayList<>();
            List<SysMenu> all = iSysMenuService.list(null);
            List<SysMenu> first = all.stream()
                    .filter(x -> x.getParentId() == null)
                    .sorted(Comparator.comparing(SysMenu::getSortCode))
                    .collect(Collectors.toList());
            for (SysMenu mo : first) {
                // generateTreeData(mo,ret,all);
                ret.add(generateTreeData(mo, all));
            }
            return ResultJson.success(ret);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    /**
     * 递归方法--SysMenu-->SysMenuTreeData
     */
    private SysMenuTreeData generateTreeData(SysMenu mo, List<SysMenu> all) {
        SysMenuTreeData node = new SysMenuTreeData();
        BeanUtils.copyProperties(mo, node);

        List<SysMenu> children = all.stream()
                .filter(x -> x.getParentId() != null && x.getParentId().equals(mo.getId()))
                .collect(Collectors.toList());
        List<SysMenuTreeData> subNodeList = new ArrayList<>();
        for (SysMenu child : children) {
            subNodeList.add(generateTreeData(child, all));
        }
        node.setChildren(subNodeList);
        return node;
    }


    //树表第三版本
    //修改菜单，选择父级菜单时，不能选择自己和自己的子节点
    @ApiOperation(value = "树表3", notes = "修改菜单，选择父级菜单时，不能选择自己和自己的子节点")
    @GetMapping(value = "/ListTreeData3")
    public ResultJson ListTreeData3(long id) {
        try {
            List<SysMenuTreeData> ret = new ArrayList<>();
            List<SysMenu> all = iSysMenuService.list(null);
            List<SysMenu> first = all.stream()
                    .filter(x -> x.getParentId() == null && x.getId() != id)
                    .sorted(Comparator.comparing(SysMenu::getSortCode))
                    .collect(Collectors.toList());
            for (SysMenu mo : first) {
                // generateTreeData(mo,ret,all);
                ret.add(generateTreeData2(mo, all, id));
            }
            return ResultJson.success(ret);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    /**
     * 递归方法--SysMenu-->SysMenuTreeData
     */
    private SysMenuTreeData generateTreeData2(SysMenu mo, List<SysMenu> all, long id) {
        SysMenuTreeData node = new SysMenuTreeData();
        BeanUtils.copyProperties(mo, node);

        List<SysMenu> children = all.stream()
                .filter(x -> x.getParentId() != null && x.getParentId().equals(mo.getId())
                        && x.getId() != id)
                .collect(Collectors.toList());
        List<SysMenuTreeData> subNodeList = new ArrayList<>();
        for (SysMenu child : children) {
            subNodeList.add(generateTreeData2(child, all, id));
        }
        node.setChildren(subNodeList);
        return node;
    }


    //树表第四版本
    //根据登录用户的角色，渲染菜单栏
    @ApiOperation(value = "树表4", notes = "根据登录用户的角色，渲染菜单栏")
    @GetMapping(value = "/ListTreeData4")
    public ResultJson ListTreeData4(long id) {
        try {
            //根据登录用户id找出用户
            SysUser sysUser = iSysUserService.getById(id);
            //在用户角色表找出userid一致的userRole
            QueryWrapper<UserRole> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userId", sysUser.getId());
            List<UserRole> userRoleList = iUserRoleService.list(queryWrapper);
            //根据userRole找出所有角色
            List<SysRole> roleList = new ArrayList<>();
            userRoleList.forEach(x -> {
                QueryWrapper<SysRole> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("id", x.getRoleId());
                SysRole sysRole = iSysRoleService.getOne(queryWrapper1);
                roleList.add(sysRole);
            });
            //根据角色查询角色菜单表
            List<RoleMenu> roleMenuList = new ArrayList<>();
            roleList.forEach(y -> {
                QueryWrapper<RoleMenu> queryWrapper2 = new QueryWrapper<>();
                queryWrapper2.eq("roleId", y.getId());
                List<RoleMenu> roleMenu = iRoleMenuService.list(queryWrapper2);
                roleMenuList.addAll(roleMenu);
            });
            //根据角色菜单查询所有菜单
            List<SysMenu> sysMenuList = new ArrayList<>();
            roleMenuList.forEach(z -> {
                QueryWrapper<SysMenu> queryWrapper3 = new QueryWrapper<>();
                queryWrapper3.eq("id", z.getMenuId());
                SysMenu sysMenu = iSysMenuService.getOne(queryWrapper3);
                if (sysMenuList.size()==0){
                   sysMenuList.add(sysMenu);
                }else {
                    for (int i = 0; i < sysMenuList.size(); i++) {
                        if (sysMenu.getId() == sysMenuList.get(i).getId()) {
                            break;
                        }else if (i == sysMenuList.size()-1) {
                            sysMenuList.add(sysMenu);
                        }
                    }
                }
            });
            List<SysMenuTreeData> ret = new ArrayList<>();
//            List<SysMenu> all = iSysMenuService.list(null);
            List<SysMenu> first = sysMenuList.stream()
                    .filter(x -> x.getParentId() == null)
                    .sorted(Comparator.comparing(SysMenu::getSortCode))
                    .collect(Collectors.toList());
            for (SysMenu mo : first) {
                // generateTreeData(mo,ret,all);
                ret.add(generateTreeData3(mo, sysMenuList));
            }
            return ResultJson.success(ret);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }
    /**
     * 递归方法--SysMenu-->SysMenuTreeData
     */
    private SysMenuTreeData generateTreeData3(SysMenu mo, List<SysMenu> all) {
        SysMenuTreeData node = new SysMenuTreeData();
        BeanUtils.copyProperties(mo, node);
        List<SysMenu> children = all.stream()
                .filter(x -> x.getParentId() != null && x.getParentId().equals(mo.getId()))
                .collect(Collectors.toList());
        List<SysMenuTreeData> subNodeList = new ArrayList<>();
        for (SysMenu child : children) {
            subNodeList.add(generateTreeData3(child, all));
        }
        node.setChildren(subNodeList);
        return node;
    }
}

